///////////////////////////////////////////////////////////////////////////////
//
// Licensed under the MIT License
//
// Copyright (c) 2010 Chris Colinsky
// All Rights Reserved
//
// version	0.5
// http://code.google.com/p/sugarcookie/
// http://code.google.com/p/sugarcookie/wiki/License
//
////////////////////////////////////////////////////////////////////////////////

package sugarcookie.data.handlers.config {
	import flash.events.EventDispatcher;
	
	import mx.logging.ILogger;
	import mx.logging.Log;
	import mx.utils.ObjectUtil;
	
	import sugarcookie.data.handlers.IDataHandler;
	import sugarcookie.data.handlers.config.vo.ViewConfig;
	import sugarcookie.error.ApplicationError;
	import sugarcookie.events.DataEvent;
	import sugarcookie.events.GenericEvent;
	import sugarcookie.file.DataLoader;
	
	/**
	 * Auto processes the config.xml file and makes it available to the DataManager.
	 */
	public class ConfigurationHandler extends EventDispatcher implements IDataHandler {
		private var _log:ILogger;
		private var _configURL:String;
		private var _xLoader:DataLoader;
		private var _configXML:XML;
		private var _viewMap:Array = [];
		private var _dynamicAutoLoad:Boolean;
		
		public function ConfigurationHandler(url:String) {
			super(this);
			_log = Log.getLogger("sugarcookie.data.handlers.config.ConfigurationHandler");
			_configURL = url;
		}
		
		public function getPath(id:String):String {
			var path:String;
			
			if (_configXML.paths.children().length()==0 || _configXML.paths.path.(@id==id)==undefined) throw new ApplicationError("The Path type does not exist!");
			else path = _configXML.paths.path.(@id==id);
			
			return path;
		}
		
		public function getURL(id:String):String {
			var url:String = null;
			
			if (_configXML.globalLinks.children().length()==0 || _configXML.globalLinks.link.(@id==id)==undefined) throw new ApplicationError("The URL type does not exist!");
			else url = _configXML.globalLinks.link.(@id==id);
			
			return url;
		}
		
		public function getJSFunction(id:String):String {
			var jsFunc:String = null;
			
			if (_configXML.javascriptMethods.children().length()==0 || _configXML.javascriptMethods.method.(@id==id)==undefined) throw new ApplicationError("The JSFunction type does not exist!");
			else jsFunc = _configXML.javascriptMethods.method.(@id==id);
			
			return jsFunc;
		}
		
		public function getService(id:String):String {
			var svc:String = null;
			
			if (_configXML.services.children().length()==0 || _configXML.services.uri.(@id==id)==undefined) throw new ApplicationError("The Service type does not exist!");
			else svc = _configXML.services.uri.(@id==id);
			
			return svc;
		}
		
		public function getViewMap():Array {
			return _viewMap;
		}
		
		public function getDefaultAutoLoadClassDef():String {
			//TODO - assumes that all views use the same data handler
			return _configXML.autoLoadData.@dataHandlerClassDef;
		}
		
		public function getIntroURI():String {
			return String(_configXML.intro.@src);
		}
		
		public function get defualtPageTitle():String {
			var title:String;
			if (_configXML.defaultPageTitle.attributes().length()!=0 && _configXML.defaultPageTitle.attribute("title")!=undefined) title = _configXML.defaultPageTitle.attribute("title");
			else title = null;
			
			return title;
		}
		
		public function get hasIntro():Boolean {
			if (_configXML.intro.@hasIntro=="true") return true;
			else return false;
		}
		
		public function get autoLoad():Boolean { return false; }
		public function set autoLoad(value:Boolean):void {  }
		
		public function get id():String { return "CONFIG"; }
		public function set id(value:String):void {  }
		
		public function kill():void {
			_xLoader = null;
		}
		
		public function init():void {
			_xLoader = new DataLoader(_configURL);
			_xLoader.addEventListener(DataLoader.ERROR,onError,false,0,true);
			_xLoader.addEventListener(DataLoader.STATUS,onStatus,false,0,true);
			_xLoader.addEventListener(DataLoader.COMPLETE,onComplete,false,0,true);
			_xLoader.load();
		}
		
		private function onError(evt:GenericEvent):void {
			dispatchEvent(new GenericEvent(DataEvent.ON_DATA_CHANNEL_ERROR,false,false,"CONFIG",true));
			throw new ApplicationError(evt.data.message);
		}
		
		private function onStatus(evt:GenericEvent):void {
			//could dispatch loading info here
		}
		
		private function onComplete(evt:GenericEvent):void {
			_configXML = new XML(_xLoader.data as String);;
			buildViewMap();
			setAutoLoadType();
			
			var initObj:Object = _configXML.autoLoadData.@auto=="true"?{handler_args:_configXML.autoLoadData.@handler_args,id:_configXML.autoLoadData.@id,dynamicAutoLoad:_dynamicAutoLoad}:null;
			var status:String = _configXML.autoLoadData.@auto=="true"?"AUTO_LOAD":"CONFIG";
			
			dispatchEvent(new DataEvent(DataEvent.ON_CONFIG_INIT,true,false,status,true,initObj));	
		}
		
		private function buildViewMap():void {
			for (var i:int=0;i<_configXML.viewMap.view.length();i++) {
				var view:XML = _configXML.viewMap.view[i];
				_viewMap[view.@id] = createViewConfig(view,i);
				var children:XMLList = _configXML.viewMap.view[i].view;
				if (children.length()>0) processChildren(children,ViewConfig(_viewMap[view.@id]));
			}
		}
		
		private function processChildren(children:XMLList,view:ViewConfig):void {
			for (var c:int=0;c<children.length();c++) {
				var child:XML = children[c];
				var childViewConfig:ViewConfig = createViewConfig(child,c);
				view.addChildView(childViewConfig);
				
				var moreChildren:XMLList = children[c].view;
				if (moreChildren.length()>0) processChildren(moreChildren,childViewConfig);
			}
		}
		
		private function createViewConfig(xml:XML,index:int):ViewConfig {
			return new ViewConfig(xml.@id,
								xml.attribute("active")!=undefined?xml.@active:"true",
								index,
								xml.@type,
								xml.@status=="internal"?"ready":null,
								xml.attribute("label")!=undefined?xml.@label:null,
								xml.attribute("title")!=undefined?xml.@title:null,
								xml.attribute("uri")!=undefined?xml.@uri:null,
								xml.attribute("dataHandlerArgs")!=undefined?xml.@dataHandlerArgs:null,
								xml.attribute("dataHandlerClassDef")!=undefined?xml.@dataHandlerClassDef:null,
								xml.attribute("viewClassDef")!=undefined?xml.@viewClassDef:null,
								xml.attribute("externalSrc")!=undefined?xml.@externalSrc:null
								);
		}
		
		private function setAutoLoadType():void {
			if (_configXML.autoLoadData.@auto=="true" && _configXML.autoLoadData.@type=="dynamic") _dynamicAutoLoad = true;
			else _dynamicAutoLoad = false;
		}
	}
}